<template>
    <div>
    </div>
</template>

<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
export default {
    data() {
        return {

        }
    },
    methods: {
        createByVertices(vertices) {
            var geometry = new THREE.BufferGeometry();
            // var p1 = new THREE.Vector3(0, 0, 0);
            // var p2 = new THREE.Vector3(0, 20, 0);
            // var p3 = new THREE.Vector3(20, 0, 0);
            console.log('---geometry', geometry)
            geometry.setFromPoints(vertices);
            // geometry.setFromPoints([p1, p2, p3]);;
            // var material = new THREE.LineBasicMaterial({
            //     // 设置红色
            //     color: 'red',
            // })
            // 随机颜色
            var color = Math.random() * 0xffffff;
            // 设置颜色
            var material = new THREE.LineBasicMaterial({
                color: color,
            });
            var mesh = new THREE.Line(geometry, material);
            return mesh
        },
        calcDir(mesh) {
            const vertices = mesh.geometry.attributes.position.array;
            const len = vertices.length;
            const meshEndPoint = new THREE.Vector3(vertices[len - 3], vertices[len - 2], vertices[len - 1]);
            // 在mesh的最后两个点方向 新创建一个向量点 以便连接
            const dir = new THREE.Vector3(vertices[len - 3] - vertices[len - 6], vertices[len - 2] - vertices[len - 5], vertices[len - 1] - vertices[len - 4])
            console.log('dir', dir)
            // 向量相加获取一条直线
            const meshTargetPoint = meshEndPoint.clone().add(dir)
            return [meshEndPoint, meshTargetPoint];
        },
        drawCircle(pos) {
            // 绘制实心圆
            var geometry = new THREE.CircleGeometry(4, 8,8);
            var material = new THREE.MeshBasicMaterial({
                color: 'red'
            });
            var circle = new THREE.Mesh(geometry, material);
            console.log('circle',new THREE.Vector3(pos.x, pos.y, pos.z))
            circle.position.copy(new THREE.Vector3(pos.x, pos.y, pos.z));
            this.scene.add(circle);
        },
        drawShapeByType(pos, targetPos, type = 1, dir = 0) {
            const getDirByVec = new THREE.Vector3().subVectors(targetPos, pos); // 方向
            console.log('getDirByVec', getDirByVec)
            // 根据type 值执行
            switch (type) {
                case 1:
                    // 绘制直线
                    return this.calcDir(this.c_line(pos, targetPos));
                case 2:
                    // 绘制弯头
                    return this.calcDir(this.c_wantou(pos, targetPos, getDirByVec, dir));
                case 3:
            }
        },
        c_line(pos, targetPos) {
            // 绘制直线
            const mesh = this.createByVertices([pos, targetPos])
            this.scene.add(mesh)
            return mesh
        },
        // 绘制弯头
        c_wantou(pos, targetPos, targetDir, dir = 0) {
            // 生成 上0、下1、左上2、左下3、右上4、右下5;六个方向的向量
            const v = [
                new THREE.Vector3(0, 1, 0),
                new THREE.Vector3(0, -1, 0),
                new THREE.Vector3(-1, 1, 0),
                new THREE.Vector3(-1, -1, 0),
                new THREE.Vector3(1, 1, 0),
                new THREE.Vector3(1, -1, 0),
            ]
            // 全部归一化处理
            v.forEach(v => {
                v.normalize();
            })
            // 获取原先方向与指定方向相比较 若相同则不可生成
            if (v[dir].equals(targetDir.clone().normalize())) {
                console.log("两个向量方向相同");
            } else {
                console.log('方向不同')
            }

            const originalGeometry = new THREE.BufferGeometry();

            // 添加原始线段的两个端点
            originalGeometry.setAttribute('position', new THREE.Float32BufferAttribute([
                ...pos, // 起点
                ...targetPos  // 终点
            ], 3));
            // 创建原始线段
            // 随机颜色
            var color = Math.random() * 0xffffff;
            // 设置颜色
            var originalMaterial = new THREE.LineBasicMaterial({
                color: color,
            });
            const originalLine = new THREE.LineSegments(originalGeometry, originalMaterial);
            this.scene.add(originalLine);

            // 转折

            // 定义衍生长度
            const len = 50; // 衍生2单位长度

            // 计算衍生点，这里使用原始线段的终点
            const originalEnd = new THREE.Vector3().fromBufferAttribute(originalGeometry.getAttribute('position'), 1);
            const derivedPoint = new THREE.Vector3().copy(originalEnd).addScaledVector(v[dir], len);
            // 创建衍生线段的几何体
            const derivedGeometry = new THREE.BufferGeometry();
            derivedGeometry.setAttribute('position', new THREE.Float32BufferAttribute([
                originalEnd.x, originalEnd.y, originalEnd.z, // 原始线段终点
                derivedPoint.x, derivedPoint.y, derivedPoint.z  // 衍生点
            ], 3));

            // 创建衍生线段的材料
            // const derivedMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });

            // 创建衍生线段
            const derivedLine = new THREE.LineSegments(derivedGeometry, originalMaterial);
            this.scene.add(derivedLine);
            return derivedLine
        },
        test() {
            // 假设 scene 是你的场景，camera 和 renderer 已经设置好

            // 创建原始线段的几何体和材料
            const originalGeometry = new THREE.BufferGeometry();
            const originalMaterial = new THREE.LineBasicMaterial({ color: 0x0000ff });

            // 添加原始线段的两个端点
            originalGeometry.setAttribute('position', new THREE.Float32BufferAttribute([
                0, 0, 0, // 起点
                100, 0, 0  // 终点
            ], 3));

            // 创建原始线段
            const originalLine = new THREE.LineSegments(originalGeometry, originalMaterial);
            this.scene.add(originalLine);

            // 定义衍生方向，例如沿着 z 轴正方向
            const direction = [
                new THREE.Vector3(0, 1, 0),
                new THREE.Vector3(0, -1, 0),
                new THREE.Vector3(-1, 1, 0),
                new THREE.Vector3(-1, -1, 0),
                new THREE.Vector3(1, 1, 0),
                new THREE.Vector3(1, -1, 0),
            ];

            // 定义衍生长度
            const len = 100; // 衍生2单位长度

            // 计算衍生点，这里使用原始线段的终点
            const originalEnd = new THREE.Vector3().fromBufferAttribute(originalGeometry.getAttribute('position'), 1);
            const derivedPoint = new THREE.Vector3().copy(originalEnd).addScaledVector(direction[2], len);
            console.log('originalEnd', originalEnd)
            console.log('derivedPoint', derivedPoint)
            console.log('len', derivedPoint.length())
            console.log('555', new THREE.Vector3().copy(originalEnd).addScaledVector(direction[5], len))
            console.log('444', new THREE.Vector3().copy(originalEnd).addScaledVector(direction[4], len))
            console.log('333', new THREE.Vector3().copy(originalEnd).addScaledVector(direction[3], len))
            console.log('222', new THREE.Vector3().copy(originalEnd).addScaledVector(direction[2], len))

            // 创建衍生线段的几何体
            const derivedGeometry = new THREE.BufferGeometry();
            derivedGeometry.setAttribute('position', new THREE.Float32BufferAttribute([
                originalEnd.x, originalEnd.y, originalEnd.z, // 原始线段终点
                derivedPoint.x, derivedPoint.y, derivedPoint.z  // 衍生点
            ], 3));

            // 创建衍生线段的材料
            const derivedMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });

            // 创建衍生线段
            const derivedLine = new THREE.LineSegments(derivedGeometry, derivedMaterial);
            this.scene.add(derivedLine);
        }
    },
    mounted() {
        var scene = this.scene = new THREE.Scene();
        /**
         * 创建网格模型
         */
        // 根据顶点数据创建mesh网格
        // var p1 = new THREE.Vector3(0, 0, 0);
        // var p2 = new THREE.Vector3(0, 20, 0);
        // var p3 = new THREE.Vector3(20, 0, 0);
        // const v = [p1, p2, p3];
        // const mesh = this.createByVertices(v);
        // console.log('mesh', mesh)
        // const [endPoint, targetPoint] = this.calcDir(mesh)
        // scene.add(mesh); //网格模型添加到场景中

        // 第一步:绘制直线
        // this.test()
        const p1 = new THREE.Vector3(0, 0, 0);
        const p2 = new THREE.Vector3(0, 50, 0);
        const [p3, p4] = this.drawShapeByType(p1, p2, 1)// 画直线
        const [p5, p6] = this.drawShapeByType(p3, p4, 2, 3)
        // console.log(endPoint2, targetPoint2)
        const [p7, p8] = this.drawShapeByType(p5, p6, 2, 2)
        const [p9, p10] = this.drawShapeByType(p7, p8, 1)// 画直线

        // 绘制实心圆
        this.drawCircle(p2)
        this.drawCircle(p4)
        this.drawCircle(p6)
        this.drawCircle(p8)
        // this.drawCircle(p10)
        // this.drawCircle(p1)

        /**
         * 光源设置
         */
        //点光源
        var point = new THREE.PointLight(0xffffff);
        point.position.set(400, 200, 300); //点光源位置
        scene.add(point); //点光源添加到场景中
        //环境光
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient);
        // console.log(scene)
        // console.log(scene.children)
        /**
         * 相机设置
         */
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 200; //三维场景显示范围控制系数，系数越大，显示的范围越大
        //创建相机对象
        var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
        camera.position.set(200, 300, 200); //设置相机位置
        camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
        /**
         * 创建渲染器对象
         */
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height);//设置渲染区域尺寸
        renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
        document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
        //执行渲染操作   指定场景、相机作为参数
        renderer.render(scene, camera);

        const controls = new OrbitControls(camera, renderer.domElement);
        controls.update();

        (function animate() {
            requestAnimationFrame(animate);
            // required if controls.enableDamping or controls.autoRotate are set to true
            controls.update();
            renderer.render(scene, camera);
        })()
    }
}
</script>
